package com.yao.spider.zhihu.task;

import com.yao.spider.core.util.Constants;
import com.yao.spider.proxy.entity.Direct;
import com.yao.spider.proxy.entity.Proxy;
import com.yao.spider.core.util.HttpClientUtil;
import com.yao.spider.proxy.ProxyPool;
import com.yao.spider.proxy.util.ProxyUtil;
import com.yao.spider.zhihu.Page;
import com.yao.spider.zhihu.ZhiHuHttpClient;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * Created by 单耀 on 2017/12/16.
 * 下载网页并解析，具体解析由子类实现
 * 若使用代理，从ProxyPool中取
 */
public abstract class AbstractPageTask implements Runnable{
    private static final Logger logger = LoggerFactory.getLogger(AbstractPageTask.class);
    protected String url;
    protected boolean proxyFlag;//是否使用代理
    protected Proxy currentProxy;
    protected HttpRequestBase request;
    protected ZhiHuHttpClient zhiHuHttpClient = ZhiHuHttpClient.getInstance();
    protected String tokenName;

    public AbstractPageTask(String url, boolean proxyFlag) {
        this.url = url;
        this.proxyFlag = proxyFlag;
    }
    public AbstractPageTask(HttpRequestBase request, boolean proxyFlag) {
        this.request = request;
        this.proxyFlag = proxyFlag;
    }

    public AbstractPageTask(HttpRequestBase request,boolean proxyFlag, String tokenName) {
        this.request = request;
        this.proxyFlag = proxyFlag;
        this.tokenName = tokenName;
    }

    public void run() {
        long requestStartTime = 0l;
        HttpGet tempRequest = null;
        String userToken = "";
        try {
            Page page = null;
            if (url != null) {
                if (proxyFlag){
                    tempRequest = new HttpGet(url);
                    //获取队列中额
                    currentProxy = ProxyPool.proxyQueue.take();
                    //
                    if (!(currentProxy instanceof Direct)) {
                        HttpHost proxy = new HttpHost(currentProxy.getIp(), currentProxy.getPort());
                        tempRequest.setConfig(HttpClientUtil.getRequestConfigBuilder().build());
                    }
                    requestStartTime = System.currentTimeMillis();
                    page = zhiHuHttpClient.getWebPage(tempRequest);
                } else {
                    requestStartTime = System.currentTimeMillis();
                    page = zhiHuHttpClient.getWebPage(tempRequest);
                }
            } else if (request != null) {

                if (proxyFlag) {
                    currentProxy = ProxyPool.proxyQueue.take();
                    if (!(currentProxy instanceof Direct)) {
                        HttpHost proxy = new HttpHost(currentProxy.getIp(), currentProxy.getPort());
                        request.setConfig(HttpClientUtil.getRequestConfigBuilder().setProxy(proxy).build());
                    }
                    requestStartTime = System.currentTimeMillis();
                    page = zhiHuHttpClient.getWebPage(request);
                }
            }
            long requestEndTime = System.currentTimeMillis();
            int status = page.getStatusCode();
            String logStr = "TokenName:" + tokenName + "; " +Thread.currentThread().getName() + " " + currentProxy +
                    "  executing request " + page.getUrl()  + " response statusCode:" + status +
                    "  request cost time:" + (requestEndTime - requestStartTime) + "ms";
            if (status == HttpStatus.SC_OK) {
                if (page.getHtml().contains("zhihu") && !page.getHtml().contains("安全验证")){
                    logger.debug(logStr);
                    currentProxy.setSuccessfulTimes(currentProxy.getFailureTimes()+ 1);
                    currentProxy.setSuccessfulTotalTime(currentProxy.getSuccessfulTotalTime() + (requestEndTime - requestStartTime));
                    double aTime = ((currentProxy.getSuccessfulTotalTime() + 0.0) / currentProxy.getSuccessfulTimes());
                    currentProxy.setSuccessfulAverageTime(aTime);
                    currentProxy.setLastSuccessfulTime(System.currentTimeMillis());
                    handle(page);

                } else {
                    //代理异常，没有正确返回目标url
                    logger.warn("proxy execption:" + currentProxy.toString());
                }
            } else if (status == 401 || status == 404 || status == 410) {
                logger.warn(logStr);
                retry();
            } else {
                logger.error(this.getClass().getSimpleName()+":"+logStr);
                Thread.sleep(100);
                retry();
            }

        } catch (InterruptedException e) {
            logger.error("InterruptedException", e);
            currentProxy.setFailureTimes(currentProxy.getFailureTimes() + 1);
        } catch (IOException e) {
            currentProxy.setFailureTimes(currentProxy.getFailureTimes() + 1);
            if (currentProxy != null) {
                //该代理可用，将该代理继续添加到proxyQueue
                ProxyPool.proxyQueue.add(currentProxy);
            }
            if (!zhiHuHttpClient.getDetailListPageThreadPool().isShutdown()) {
                retry();
            }
        } finally {
            if (request != null) {
                request.releaseConnection();
            }
            if (tempRequest != null) {
                tempRequest.releaseConnection();
            }

            if (currentProxy != null && !ProxyUtil.isDiscardProxy(currentProxy)) {
                currentProxy.setTimeIntervsl(Constants.TIME_INTERVAL);
                ProxyPool.proxyQueue.add(currentProxy);
            }
        }
    }

    /**
     * 子类实现page处理
     * @param page
     */
    public abstract void handle(Page page);

    public abstract void retry();
}
